package com.eian.boot.common.id.generator.sequence;

import com.eian.boot.common.id.exception.IdGenerationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;

/**
 * Redis序列号生成器
 *
 * @author alex.meng
 */
@Slf4j
@RequiredArgsConstructor
public class RedisSequenceGenerator extends AbstractSequenceGenerator {

    /**
     * Redis Key前缀
     */
    private static final String KEY_PREFIX = "id:sequence:";
    private final RedissonClient redissonClient;

    @Override
    public long nextSequence(String bizType) {
        checkRedissonClient();
        try {
            String key = KEY_PREFIX + bizType;
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);

            // 原子性递增
            long sequence = atomicLong.incrementAndGet();
            log.debug("获取Redis序列号成功：bizType={}, sequence={}", bizType, sequence);
            return sequence;
        } catch (Exception e) {
            log.error("获取Redis序列号异常：bizType={}", bizType, e);
            throw new IdGenerationException("ID序列号生成失败（Redis）：" + e.getMessage(), e);
        }
    }

    @Override
    public void resetSequence(String bizType) {
        checkRedissonClient();
        try {
            String key = KEY_PREFIX + bizType;
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
            atomicLong.set(0L);
            log.info("Redis序列号重置成功：bizType={}", bizType);
        } catch (Exception e) {
            log.error("重置Redis序列号异常：bizType={}", bizType, e);
            throw new IdGenerationException("ID序列号重置失败（Redis）：" + e.getMessage(), e);
        }
    }

    /**
     * 设置业务类型的起始值
     *
     * @param bizType   业务类型
     * @param initValue 初始值
     */
    public void setInitValue(String bizType, long initValue) {
        checkRedissonClient();
        try {
            String key = KEY_PREFIX + bizType;
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
            atomicLong.set(initValue);
            log.info("设置Redis序列号初始值成功：bizType={}, initValue={}", bizType, initValue);
        } catch (Exception e) {
            log.error("设置Redis序列号初始值异常：bizType={}, initValue={}", bizType, initValue, e);
            throw new IdGenerationException("设置Redis序列号初始值失败：" + e.getMessage(), e);
        }
    }

    /**
     * 检查RedissonClient是否已配置
     */
    private void checkRedissonClient() {
        if (redissonClient == null) {
            throw new IdGenerationException(
                    "RedissonClient未配置，无法使用Redis序列号生成器。" +
                            "\n请在application.yml中添加Redisson配置：" +
                            "\nspring.data.redis.redisson.config: |" +
                            "\n  singleServerConfig:" +
                            "\n    address: \"redis://localhost:6379\"" +
                            "\n    database: 0"
            );
        }
    }
}

